package middleware

import (
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"github.com/parnurzeal/gorequest"
	"go.uber.org/zap"
	"net/http"
	"qmp_go_push/conf"
	"qmp_go_push/models"
	"qmp_go_push/pkg/logger"
	"qmp_go_push/pkg/response"
)

const (
	RequestParamKey string = "_req_param_key"
)

type VerifyTokenReq struct {
	Token string `json:"token"`
}
type VerifyTokenRes struct {
	Data VerifyTokenData `json:"data"`
}

type VerifyTokenData struct {
	UserUuid string `json:"user_uuid"`
	Salt     string `json:"salt"`
	Src      int    `json:"src"`
	Way      int    `json:"way"`
	Env      string `json:"env"`
}

// CheckAdminApiAuth 校验后台管理的账号身份
func CheckAdminApiAuth() gin.HandlerFunc {
	return func(context *gin.Context) {
		if context.Request.URL.Path == "/api/admin/login" ||
			context.Request.URL.Path == "/api/admin/sendSms" {
			context.Next()
			return
		}
		var (
			res VerifyTokenRes
			req = VerifyTokenReq{
				Token: context.GetHeader("Authorization"),
			}
		)

		_, bodyStr, err := gorequest.New().Post(conf.CONFIG.VerifyToken.VerifyUrl).Type("multipart").Send(req).End()
		if err != nil {
			logger.Info(logger.ErrLogger, "CheckAdminApiAuth POST err", zap.Any("req", req), zap.Any("resp", bodyStr), zap.Any("err", fmt.Sprintf("%v", err)))
			context.AbortWithStatusJSON(http.StatusOK, response.Response{
				Status:  response.ErrInvalidToken.Code,
				Message: response.ErrInvalidToken.Message.Error(),
			})
			return
		}

		_ = json.Unmarshal([]byte(bodyStr), &res)
		if len(res.Data.UserUuid) == 0 {
			context.AbortWithStatusJSON(http.StatusOK, response.Response{
				Status:  response.ErrInvalidToken.Code,
				Message: response.ErrInvalidToken.Message.Error(),
			})
			return
		}

		teamInfo := models.GetTeamInfoByUserUuid(res.Data.UserUuid)
		if len(teamInfo.TeamUuid) == 0 {
			context.AbortWithStatusJSON(http.StatusOK, response.Response{
				Status:  response.ErrNotTeam.Code,
				Message: response.ErrNotTeam.Message.Error(),
			})
			return
		}
		if teamInfo.IsBan > 0 {
			context.AbortWithStatusJSON(http.StatusOK, response.Response{
				Status:  response.ErrUserIsBan.Code,
				Message: response.ErrUserIsBan.Message.Error(),
			})
			return
		}
		if teamInfo.IsQuit > 0 {
			context.AbortWithStatusJSON(http.StatusOK, response.Response{
				Status:  response.ErrUserIsQuit.Code,
				Message: response.ErrUserIsQuit.Message.Error(),
			})
			return
		}
		context.Set("team_uuid", teamInfo.TeamUuid)
		context.Set("user_uuid", res.Data.UserUuid)
		context.Next()
	}
}

func CrossDomain() gin.HandlerFunc {
	return func(context *gin.Context) {
		context.Header("Access-Control-Allow-Origin", "*")
		context.Header("Access-Control-Allow-Headers", "Authorization,Content-Type")
		context.Header("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE")

		context.Next()
	}
}

func ParseJson() gin.HandlerFunc {
	return func(context *gin.Context) {
		var body []byte
		switch context.ContentType() {
		case binding.MIMEJSON:
			body, _ = context.GetRawData()
			context.Set(RequestParamKey, body)
		case binding.MIMEPOSTForm:
			context.Request.ParseForm()
			postForm := context.Request.PostForm
			body = []byte(postForm.Encode())
			context.Set(RequestParamKey, body)
		case binding.MIMEMultipartPOSTForm:
			form, _ := context.MultipartForm()
			body, _ = json.Marshal(form)
			context.Set(RequestParamKey, body)
		}
		logger.Info(logger.BizLogger, "ParseJson", zap.Any("body", string(body)))
		context.Next()
	}
}
